package com.example.demo.admin.sync.utils;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.FutureRequestExecutionService;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpRequestFutureTask;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
	private static final CloseableHttpClient httpClient;
	private static final String CHARSET = "UTF-8";
	private static Integer connectTimeout = 6000000;
	private static Integer socketTimeout = 1500000;
	private static ExecutorService executorService = Executors.newFixedThreadPool(2);

	static {
		RequestConfig config = RequestConfig.custom().setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout)
				.build();
		httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
	}

	/**
	 * HTTP Get 获取内容
	 * 
	 * @param url 请求的url地址?之前的地址
	 * @param params 请求的参数
	 *  charset编码格式
	 * @return 页面内容
	 */
	public static String sendGet(String url, Map<String, Object> params) {
		if (StringUtils.isEmpty(url)) {
			return "";
		}
		try {
			url = createUrl(url, params);
			HttpGet httpGet = new HttpGet(url);
			CloseableHttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != 200) {
				httpGet.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			String result = null;
			if (entity != null) {
				result = EntityUtils.toString(entity, CHARSET);
			}
			EntityUtils.consume(entity);
			response.close();
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 发送异步get请求，
	 * @param url
	 * @param params
	 * @return
	 */
	public static String asyncSendGet(String url, Map<String, Object> params) {

		FutureRequestExecutionService requestExecService = new FutureRequestExecutionService(httpClient,executorService);

		try {
			url = createUrl(url, params);
			HttpGet httpGet = new HttpGet(url);
			HttpRequestFutureTask<String> futureTask = requestExecService.execute(httpGet, HttpClientContext.create(),HttpUtils::handleResponse);

			return  futureTask.get();

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;


	}

	public static String createUrl(String url, Map<String, Object> params) throws IOException {
		if (params != null && !params.isEmpty()) {
            List<NameValuePair> pairs = new ArrayList<NameValuePair>(params.size());
            for (String key : params.keySet()) {
                pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
            }
            url += "?" + EntityUtils.toString(new UrlEncodedFormEntity(pairs, CHARSET));
        }
		return url;
	}



	/**
	 * json 格式 post请求
	 * @param url
	 * @param jsonData
	 * @return
	 */
	public static String sendPostJson(String url,String jsonData){
		if (StringUtils.isEmpty(url)) {
			return "";
		}

		logger.info("==>url=[" + url +"]");

		try {
			HttpPost post = new HttpPost(url);

			StringEntity entity = new StringEntity(jsonData,"utf-8");
			entity.setContentEncoding("UTF-8");
			entity.setContentType("application/json");

			post.setEntity(entity);

			CloseableHttpResponse result = httpClient.execute(post);

			int statusCode = result.getStatusLine().getStatusCode();
			if (statusCode != 200) {
				post.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}

			String resultData = null;
			if (entity != null) {
				resultData = EntityUtils.toString(result.getEntity(), CHARSET);
			}

			result.close();

			return resultData;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
         * HTTP Post 获取内容
         *
         * @param url 请求的url地址?之前的地址
         * @param params 请求的参数
         *  charset 编码格式
         * @return 页面内容
         */
	public static String sendPost(String url, Map<String, Object> params) {
		if (StringUtils.isEmpty(url)) {
			return "";
		}

		logger.info("==>url=[" + url +"]");
		try {
			List<NameValuePair> pairs = null;
			if (params != null && !params.isEmpty()) {
				pairs = new ArrayList<NameValuePair>(params.size());
				for (String key : params.keySet()) {
					pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
				}
			}
			HttpPost httpPost = new HttpPost(url);
			if (pairs != null && pairs.size() > 0) {
				httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
			}
			CloseableHttpResponse response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != 200) {
				httpPost.abort();
				throw new RuntimeException("HttpClient,error status code :" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			String result = null;
			if (entity != null) {
				result = EntityUtils.toString(entity, CHARSET);
			}
			EntityUtils.consume(entity);
			response.close();

			logger.info("==>result=[" + result +"]");
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 异步回调函数
	 * @param response
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode != 200) {
			throw new RuntimeException("HttpClient,error status code :" + statusCode);
		}
		HttpEntity entity = response.getEntity();
		String result = null;
		if (entity != null) {
			result = EntityUtils.toString(entity, CHARSET);
		}
		EntityUtils.consume(entity);
		return result;
	}

	/**
	 * 异步发送post请求
	 * @param url
	 * @param params
	 * @return
	 */
	public static String asyncSendPost(String url, Map<String, Object> params,boolean abortResult) {
		if (StringUtils.isEmpty(url)) {
			return "";
		}

		FutureRequestExecutionService requestExecService = new FutureRequestExecutionService(httpClient,executorService);



		try {
			List<NameValuePair> pairs = null;
			if (params != null && !params.isEmpty()) {
				pairs = new ArrayList<NameValuePair>(params.size());
				for (String key : params.keySet()) {
					pairs.add(new BasicNameValuePair(key, params.get(key).toString()));
				}
			}
			HttpPost httpPost = new HttpPost(url);
			if (pairs != null && pairs.size() > 0) {
				httpPost.setEntity(new UrlEncodedFormEntity(pairs, CHARSET));
			}

			HttpRequestFutureTask<String> futureTask = requestExecService.execute(httpPost, HttpClientContext.create(),HttpUtils::handleResponse);

			if(abortResult) return null;
			return  futureTask.get();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}
		public static void main(String[] args) {
		String url = "http://localhost:8088/mvc/testController";
		Map<String, String> map = new HashMap<String, String>();
		map.put("char", "!@#$%^&*()");
		map.put("char2", "!@#$%^&*()(*&^%$#@!@#$%^&");
		String json= JSON.toJSONString(map);

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("a", json);
		String result = asyncSendGet(url, params);
		System.out.println(result);

	}
}
